package org.KeyCrafter.server.handler;

import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.KeyCrafter.server.session.ClientSession;
import org.KeyCrafter.server.ServerContext;

/**
 * 服务端
 * 涉及客户端连接管理、消息接收、异常处理
 * 按理来讲每个需要加上注解：@ChannelHandler.Sharable 以确保线程安全
 */
@ChannelHandler.Sharable
public class CommonAcceptor extends ChannelInboundHandlerAdapter {
    ServerContext sc = ServerContext.DEFAULT;
    // 连接处理器
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        // 创建客户端
        ClientSession c = new ClientSession(channel);
        // 将客户端与 channel 绑定
        channel.attr(ClientSession.ATTRIBUTE_KEY).set(c);
        // 添加到服务器
        sc.addClient(c);
    }

    // 在解码前保存原始数据
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ClientSession c = ctx.channel().attr(ClientSession.ATTRIBUTE_KEY).get();
        sc.setCurrentClient(c);
        // 加入到查询缓冲区
        if (msg instanceof ByteBuf) {
            if (c.getQueryBuf().refCnt() == 0) {
                // 校验如若没有初始化，则创建一个新的缓冲区，并将其设置为客户端的查询缓冲区。
                c.setQueryBuf(ctx.channel().alloc().compositeBuffer());
            }
            // 添加消息到客户端缓冲区
            c.getQueryBuf().addComponent(true, (ByteBuf) msg);
            //System.out.println(((ByteBuf)msg).toString(CharsetUtil.UTF_8));
        }
        ctx.fireChannelRead(msg);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        //System.out.println("正常退出");
        ClientSession c = ctx.channel().attr(ClientSession.ATTRIBUTE_KEY).get();
        c.getQueryBuf().release();
        c.getReplyBuffer().release();
        ctx.close();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("异常退出: " + cause.getMessage());
        ClientSession c = ctx.channel().attr(ClientSession.ATTRIBUTE_KEY).get();
        c.getQueryBuf().release();
        c.getReplyBuffer().release();
        ctx.close();
    }
}